home *** CD-ROM | disk | FTP | other *** search
/ Exploring Creation with P…al Science (2nd Edition) / Exploring Creation with Physical Science (2nd Edition).iso / exe / bin / Styles / webfeeds.html < prev    next >
Encoding:
Extensible Markup Language  |  2012-12-18  |  13.5 KB  |  565 lines

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
  4. <head>
  5. <title>Feed preview</title>
  6. <style type="text/css">
  7.  
  8. html,
  9. body
  10. {
  11.     margin:0;
  12.     padding:0;
  13.     border:0;
  14. }
  15. body
  16. {
  17.     color:#000;
  18.     background:#fff;
  19.     text-align:center;
  20.     font:normal normal .9em/1.5em sans-serif;
  21.     padding:2em 0;
  22. }
  23. body[class]:after
  24. {
  25.     position:fixed;
  26.     top:0;
  27.     left:0;
  28.     right:0;
  29.     bottom:0;
  30.     background:#fff;
  31.     content:attr(class);
  32.     text-transform:uppercase;
  33.     padding-top:30%;
  34.     text-align:center;
  35. }
  36. h1
  37. {
  38.     margin:0;
  39.     font-size:1.5em;
  40.     line-height:1.5em;
  41.     display:inline;
  42. }
  43. h1:before
  44. {
  45.     display:inline;
  46.     overflow:hidden;
  47.     vertical-align:middle;
  48.     content:-o-skin('Mail Newsfeeds');
  49.     margin-right:.2em;
  50.     line-height:1.5em;
  51. }
  52.  
  53. #heading
  54. {
  55.     background:#a00 url(data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%04%00%00%00%C0%08%06%00%00%00%23%88%C2%DC%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%00%3AIDATx%DA%EC%D0%21%0E%000%08%04Ah%8A%EF%FF%3F%7BE%12%0C%02%BB%9B%9C%19y.%C9j%C7Z%00%00%00%000%82%E7%A2%C2%CD%BD%0E%C1c%00%00%00%C0%0E%BE%00%03%00k%9B%04%9A%B9%BDH%AF%00%00%00%00IEND%AEB%60%82) repeat-x center center;
  56.     color:#fff;
  57.     padding:8px;
  58.     margin:1em 0;
  59.     border:2px solid #eee;
  60.     border-width:2px 0;
  61. }
  62. #heading > *
  63. {
  64.     display:inline-block;
  65.     width:50ex;
  66.     line-height:2em;
  67. }
  68. #heading a
  69. {
  70.     color:#fff;
  71. }
  72. #heading button
  73. {
  74.     margin:0 10ex;
  75.     width:30ex;
  76. }
  77.  
  78. a
  79. {
  80.     text-decoration:none;
  81. }
  82.  
  83. a:hover
  84. {
  85.     text-decoration:underline;
  86. }
  87. #items
  88. {
  89.     display:block;
  90.     clear:both;
  91.     text-align:center;
  92.     margin:2em 0;
  93.     padding:0;
  94.     overflow:hidden;
  95. }
  96.  
  97. #items > ul
  98. {
  99.     position:relative;
  100.     list-style:none;
  101.     margin:0;
  102.     padding:0;
  103.     border:0;
  104.     width:auto;
  105.     display:inline-block;
  106.     text-align:left;
  107. }
  108. #items > ul > li:last-child
  109. {
  110.     display:none;
  111. }
  112. #items > ul > li
  113. {
  114.     vertical-align:top;
  115.     font:normal normal .8em/1.6em sans-serif;
  116.     display:inline-block;
  117.     margin:2em;
  118.     padding:0;
  119.     width:50ex;
  120. }
  121. #items > ul > li > h2
  122. {
  123.     font:normal lighter 1.66em/1.2em sans-serif;
  124.     margin:0;
  125.     color:#000;
  126.     overflow:hidden;
  127.     -o-text-overflow:ellipsis;
  128. }
  129. #items > ul > li > h2 > a
  130. {
  131.     display:block;
  132.     color:inherit;
  133.     padding:0;
  134. }
  135. #items > ul > li a
  136. {
  137.     color:#b00;
  138. }
  139. #items > ul > li > div
  140. {
  141.     border-top:1px solid #ccc;
  142.     text-align:justify;
  143.     margin:1em 0 0 0;
  144.     padding:1em 0 3em 0;
  145.     color:#555;
  146.     vertical-align:top;
  147.     -o-text-overflow:ellipsis;
  148. }
  149. #items > ul > li > div pre
  150. {
  151.     font:.9em/.9em monospace;
  152.     background:#eee;
  153.     overflow:auto;
  154.     border:1px solid #999;
  155.     border-width:1px 0;
  156.     padding:1em;
  157. }
  158. #items > ul > li > div pre a
  159. {
  160.     font-style:normal;
  161. }
  162.  
  163. #items > ul > li > div p
  164. {
  165.     margin:0 0 2em 0;
  166. }
  167. #items > ul > li > div a
  168. {
  169.     font-style:italic;
  170.     margin-right:.25em;
  171. }
  172. #items > ul > li > div img
  173. {
  174.     display:none;
  175. }
  176. #items > ul > li > div img[src]
  177. {
  178.     float:left;
  179.     display:inline-block;
  180.     border:1px solid #aaa;
  181.     padding:1px;
  182.     margin:1px;
  183.     margin:1px 8px 8px 1px;
  184.     max-width:100%;
  185. }
  186. #items > ul > li > div a img[src]
  187. {
  188.     border-color:#a00;
  189. }
  190. #items > ul > li > div a:hover img
  191. {
  192.     border-width:2px;
  193.     margin:0px 7px 7px 0px;
  194. }
  195. #footer
  196. {
  197.     font-size:.85em;
  198. }
  199. #footer a
  200. {
  201.     color:#b00;
  202. }
  203.  
  204. /*
  205.  *  extra rules for HANDHELD devices
  206.  */
  207. @media handheld
  208. {
  209.     body
  210.     {
  211.         font:normal normal 1em/1.5em sans-serif;
  212.         padding:1em 0;
  213.     }
  214.     #heading > *,
  215.     #heading > button
  216.     {
  217.         display:inline;
  218.         width:auto;
  219.         margin:0 .5em;
  220.         line-height:auto;
  221.         height:auto;
  222.     }
  223.     #items
  224.     {
  225.         margin:1em 0;
  226.     }
  227.     #items > ul
  228.     {
  229.         display:block;
  230.     }
  231.     #items > ul > li
  232.     {
  233.         font:normal normal 1em/1.5em sans-serif;
  234.         display:block;
  235.         padding:1em;
  236.         margin:0;
  237.         width:auto;
  238.         background:#fff;
  239.     }
  240.     #items > ul > li:nth-child(2n)
  241.     {
  242.         background:#eee;
  243.     }
  244.     #items > ul > li > h2
  245.     {
  246.         font:normal bold 1.33em/1.2em sans-serif;
  247.     }
  248.     #items > ul > li > div
  249.     {
  250.         border:0;
  251.         padding:0;
  252.         margin:0;
  253.     }
  254.     #items > ul > li > div:after
  255.     {
  256.         clear:both;
  257.         content:' ';
  258.         display:block;
  259.     }
  260.     #items > ul > li > div pre
  261.     {
  262.         font:1em/1em monospace;
  263.         background:#ddd;
  264.     }
  265.     #items > ul > li > div a
  266.     {
  267.         font-style:normal;
  268.     }
  269.     #footer a
  270.     {
  271.         font-size:1em;
  272.     }
  273. }
  274.  
  275.  
  276. </style>
  277. <script type="text/javascript">
  278. // <![CDATA[
  279.  
  280. String.prototype.trim = function()
  281. {
  282.     return this.replace( /^\s+|\s+$/g, '' );
  283. }
  284.  
  285. /*
  286.  *    whiteList
  287.  *    tags + attributes and method to validate them
  288.  */
  289. HTMLElement.prototype.whiteList =
  290. {
  291.     'A':
  292.     {
  293.         '__precondition__':function( node )
  294.         {
  295.             return node.hasAttribute('href') && node.whiteList['A'].href.call( {value:node.getAttribute('href')}, node );
  296.         },
  297.         'href':function( node )
  298.         {
  299.             return null!=this.value.match( /^https?:\/\//i );
  300.         },
  301.         'title':true
  302.     }
  303.     ,'IMG':
  304.     {
  305.         '__precondition__':function( node )
  306.         {
  307.             node.setAttribute( 'title', node.getAttribute('title')||node.getAttribute('src') )
  308.             return node.hasAttribute('src') && node.whiteList['IMG'].src.call( {value:node.getAttribute('src')}, node );
  309.         },
  310.         'src':function( node )
  311.         {
  312.             return null!=this.value.match( /^https?:\/\//i );
  313.         },
  314.         'alt':true,
  315.         'title':true
  316.     }
  317.     ,'P':{}
  318.     ,'PRE':{}
  319.     ,'UL':{}
  320.     ,'OL':{}
  321.     ,'LI':{}
  322.     ,'DL':{}
  323.     ,'DT':{}
  324.     ,'H1':{}
  325.     ,'H2':{}
  326.     ,'H3':{}
  327.     ,'H4':{}
  328.     ,'H5':{}
  329.     ,'H6':{}
  330.     ,'BR':{}
  331. }
  332. /**
  333.  *    Prototype extension to simplify adding and sanitizing markup to an element.
  334.  *    arguments = some strings containing the HTML markup to sanitize and append
  335.  */
  336. HTMLElement.prototype.appendMarkup = function( content, maxLength )
  337. {
  338.     var    maxLength   = maxLength||Infinity,
  339.            dummy       = document.createElement('div');
  340.     dummy.innerHTML    = content;
  341.  
  342.     //  sanitize using the whiteList
  343.     dummy.sanitize();
  344.  
  345.     //    append DOM tree of dummy in this
  346.     var i = 0, node;
  347.     while( maxLength>this.textContent.length && dummy.firstChild )
  348.     {
  349.         this.appendChild( dummy.firstChild );
  350.         i++;
  351.     }
  352.  
  353.     //maxLength = Infinity;
  354.     if( dummy.firstChild && maxLength!=Infinity )
  355.     {
  356.         this.cutOff( maxLength );
  357.     }
  358.  
  359.  
  360.     return this;
  361. }
  362. /**
  363.  *    Prototype extension to sanitize the attributes and HTMLElements
  364.  *    whiteList = { 'NODENAME_0':{'attribute_0':function(){},'attribute_1':function(){}} }
  365.  */
  366. HTMLElement.prototype.sanitize = function()
  367. {
  368.     // recurse
  369.     var i=0, previousNodeName='/', currentNode;
  370.     while( currentNode=this.childNodes[i] )
  371.     {
  372.         var nodeName    = currentNode.nodeName;
  373.  
  374.         if
  375.         (
  376.             currentNode.nodeType==1
  377.             &&
  378.             (
  379.                     !this.whiteList[nodeName]
  380.                 ||  ( this.whiteList[nodeName] && this.whiteList[nodeName].__precondition__ && !this.whiteList[nodeName].__precondition__(currentNode) )
  381.                 ||  ( nodeName=='BR' && ( previousNodeName=='BR' || previousNodeName=='P' ) )
  382.             )
  383.         )
  384.         {
  385.             // either it's not in the whiteList or does not meet the preconditions or is an extra BR -> replace currentNode by its content
  386.             while( currentNode.firstChild )
  387.             {
  388.                 this.insertBefore( currentNode.firstChild.cloneNode( true ), currentNode );
  389.                 currentNode.removeChild( currentNode.firstChild );
  390.             }
  391.             this.removeChild( currentNode );
  392.         }
  393.         else
  394.         {
  395.             if( currentNode.nodeType==1 )
  396.             {
  397.                 //  in the whiteList and meet the preconditions
  398.                 //    -> sanitize the attributes
  399.                 for( var j=currentNode.attributes.length,attribute; attribute=currentNode.attributes[--j]; )
  400.                 {
  401.                     var attrSanity = this.whiteList[nodeName][attribute.name];
  402.                     if( attrSanity===undefined || ( attrSanity!==true && false==attrSanity.apply(attribute,[currentNode] ) ) )
  403.                     {
  404.                         currentNode.removeAttribute( attribute.name );
  405.                     }
  406.                 }
  407.  
  408.                 //  -> and recurse
  409.                 currentNode.sanitize();
  410.                 previousNodeName = nodeName;
  411.             }
  412.             //  => next!
  413.             i++;
  414.         }
  415.     }
  416. }
  417. /*
  418.  *    Prototype extension to cutOff a DOM tree so as to get a textContent <= maxLength
  419.  */
  420. Element.prototype.cutOff = function( maxLength, base )
  421. {
  422.     var base = base||this;
  423.     while( this.lastChild )
  424.     {
  425.         if( this.lastChild.nodeType==3 && this.lastChild.nodeValue.length>base.textContent.length-maxLength )
  426.         {
  427.             this.lastChild.nodeValue = this.lastChild.nodeValue.slice( 0, this.lastChild.nodeValue.length-base.textContent.length+maxLength ) +'...';
  428.             return true;
  429.         }
  430.         if( this.lastChild.nodeType==1 && this.lastChild.cutOff( maxLength, base ) )
  431.         {
  432.             return true;
  433.         }
  434.         this.removeChild( this.lastChild );
  435.     }
  436.     return false;
  437. }
  438.  
  439.  
  440. //  failsafe for opera.locale.getLocaleString
  441. opera.locale=opera.locale||{'getLocaleString':function(){return ''}};
  442.  
  443. /*
  444.  *  outputFeed
  445.  */
  446. function outputFeed( feed, status )
  447. {
  448.     if( !feed )
  449.     {
  450.         var statusName = ['NO FEED ITEMS','CANCELED','REFRESH POSTPONED','NOT MODIFIED','OUT OF MEMORY','SERVER TIMEOUT','LOADING ERROR','PARSING ERROR']
  451.         document.body.className = 'error #'+ status +' ( '+ statusName[ status ] +' )';
  452.         return false;
  453.     }
  454.  
  455.     //  l10n the 'footer' note including a link
  456.     var footer      = document.getElementById('footer'),
  457.         splitText   = (opera.locale.getLocaleString( 'S_WEBFEEDS_FOOTER' )||'This page was generated by Opera from %s').split('%s');
  458.  
  459.     footer.firstChild.nodeValue = splitText.shift()||'';
  460.     footer.lastChild.nodeValue = splitText.join(' ')||'';
  461.  
  462.  
  463.     //  l10n the 'learn' link
  464.     (document.getElementById('learn')||{firstChild:{}}).firstChild.nodeValue = opera.locale.getLocaleString( 'S_WEBFEEDS_SUBSCRIBE_HINT' )||'Learn more about feeds';
  465.  
  466.     //  subscribeNative?
  467.     var button = document.getElementById('subscribe');
  468.     if( button )
  469.     {
  470.         if( 'function'==typeof(opera.feeds.subscribeNative) )
  471.         {
  472.             button.addEventListener( 'click', function(){ opera.feeds.subscribeNative(location.href); }, false );
  473.             //  l10n the 'subscribe' button
  474.             button.firstChild.nodeValue = opera.locale.getLocaleString( 'S_MINI_FEED_SUBSCRIBE' )||'Subscribe';
  475.         }
  476.         else
  477.         {
  478.             button.parentNode.removeChild( button );
  479.         }
  480.     }
  481.  
  482.     //    set title
  483.     top.document.title = document.getElementById('feedTitle').firstChild.nodeValue = document.createElement( 'div' ).appendMarkup( feed.title.data ).textContent.trim()||feed.uri;
  484.     document.body.removeAttribute( 'class' );
  485.  
  486.     //  walk the feed items
  487.     var cutOff      = 768,
  488.         hItemsUl    = document.getElementById('itemsUl'),
  489.         noTilteStr  = opera.locale.getLocaleString( 'M_BREW_NO_TITLE' )||'<No Title>';
  490.     for( var i=0,feedEntry; feedEntry=feed.entries[i++]; )
  491.     {
  492.         var itemLi = hItemsUl.lastChild.cloneNode( true );
  493.  
  494.         //  set the href
  495.         itemLi.firstChild.firstChild.setAttribute( 'href', feedEntry.uri||'#' );
  496.  
  497.         //  set the title
  498.         itemLi.firstChild.firstChild.firstChild.nodeValue = document.createElement( 'div' ).appendMarkup( feedEntry.title.data ).textContent.trim()||noTilteStr;
  499.  
  500.         //  write content
  501.         if( feedEntry.content.isMarkup )
  502.         {
  503.             itemLi.lastChild.appendMarkup( (feedEntry.content.data.trim()||'\xa0'), cutOff );
  504.         }
  505.         else if( feedEntry.content.isPlainText )
  506.         {
  507.             itemLi.lastChild.appendChild( document.createTextNode( (feedEntry.content.data.trim()||'\xa0').slice( 0, cutOff ) ) );
  508.         }
  509.         else
  510.         {
  511.             itemLi.lastChild.appendChild( document.createTextNode( (feedEntry.content.data||'\xa0').slice( 0, cutOff ) ) );
  512.         }
  513.  
  514.         //  append itemLi to hItemsUl
  515.         hItemsUl.insertBefore( itemLi, hItemsUl.lastChild );
  516.     }
  517.  
  518.     return true;
  519. }
  520.  
  521. // ]]>
  522. </script>
  523. </head>
  524. <body class='loading'>
  525.  
  526.     <h1 id="feedTitle">Title of the news feed</h1>
  527.     <div id="heading"><span><a id="learn" href="opera:/help/feeds.html">Learn more about feeds</a></span><button id="subscribe">Subscribe</button></div>
  528.  
  529.     <div id="items">
  530.         <ul id="itemsUl"><!-- template LI follows --><li><h2><a href="#">...</a></h2><div></div></li></ul>
  531.     </div>
  532.  
  533.  
  534.  
  535.     <div id="footer">This page was generated by Opera from <a href="#">here</a>.</div>
  536.  
  537. <script type="text/javascript">
  538. // <![CDATA[
  539.  
  540. window.addEventListener
  541. (
  542.     'load',
  543.     function(/* window.load */)
  544.     {
  545.         var url     = location.href.split('#')[0],
  546.             here    = document.getElementById('footer').getElementsByTagName('A')[0],
  547.             theFeed = null;
  548.  
  549.         for( var i=0; theFeed=opera.feeds.allFeeds[i++]; )
  550.         {
  551.             if( url==theFeed.uri.split('#')[0] )
  552.             {
  553.                 here.firstChild.nodeValue = here.href = theFeed.uri;
  554.                 break;
  555.             }
  556.         }
  557.         outputFeed( theFeed );
  558.     },
  559.     false
  560. );
  561.  
  562. //]]>
  563. </script>
  564. </body>
  565. </html>